///////////////////////////////////////////////////////////////////////////////
//
// Licensed under the MIT License
//
// Copyright (c) 2010 Chris Colinsky
// All Rights Reserved
//
// version	0.5
// http://code.google.com/p/sugarcookie/
// http://code.google.com/p/sugarcookie/wiki/License
//
////////////////////////////////////////////////////////////////////////////////

package sugarcookie.data.handlers.flex.remoting {
	import flash.events.EventDispatcher;
	
	import mx.logging.*;
    import mx.logging.ILogger;
    
    import mx.utils.ObjectUtil;
	
	import sugarcookie.data.handlers.flex.remoting.RemotingServiceHandler;
	import sugarcookie.data.handlers.flex.remoting.events.RemotingServiceResultEvent;

	public class RemotingServiceManager extends EventDispatcher {
		private var _log:ILogger;
		private var _lastResult:Object;
		private static var remoteStack:Object = new Object();
		
		public function set lastResult(r:Object):void {
			_lastResult = r;
		}
		
		public function get lastResult():Object {
			return _lastResult;
		}
		
		public function RemotingServiceManager() {
			_log = Log.getLogger("sugarcookie.dataHandlers.RemotingServiceManager");
		}
		
		/**
		 * TODO: Need to upgrade to support multiple destinations with multiple sources per destination.
		 **/
		public function addService(destination:String,service:String,evtType:String):void {
			if (!remoteStack[destination]) remoteStack[destination] = new RemotingServiceHandler(this,destination,service);
			remoteStack[destination].addEventListener(RemotingServiceHandler.FAULT_EVENT,dispatchFault);
		}
		
		public function callService(destination:String,method:String,evtType:String,...args:Array):Boolean {
			if (!remoteStack[destination] || destination==null || method==null) return false;
			
			remoteStack[destination].addEventListener(evtType,dispatchResult);
			if (args.length == 0) {
				_log.debug("No arguments we're received.");
				remoteStack[destination].call(method,evtType);
			} else {
				remoteStack[destination].call(method,evtType,args);
			}
			
			return true;
		}
		
		public function dispatchResult(result:RemotingServiceResultEvent):void {
			try {
        		if (!dispatchEvent(result)) {
					_log.error("Unable to dispatch result event from "+result.remoteDest);
				}
        	} catch (err:Error) {
        		_log.error("handleResults dispatchEvent error: "+err.toString());
        	}
			
			remoteStack[result.remoteDest].removeEventListener(remoteStack[result.remoteDest].eventType,dispatchResult);
		}
		
		public function dispatchFault(fault:RemotingServiceResultEvent):void {
			try {
        		if (!dispatchEvent(fault)) {
	        		_log.error("Unable to dispatch fault event from "+fault.remoteDest+": \n"+ObjectUtil.toString(fault));
	        	}
        	} catch (err:Error) {
        		_log.error("handleFault dispatchEvent error: "+err.toString());
        	}
		}
	}
}